package io.cici.cc.mybatis.lite.parse;


import lombok.NonNull;

/**
 * @author huihui
 */
public class TokenParser {

    private final String openToken;
    private final String closeToken;
    private final TokenHandler tokenHandler;

    public TokenParser(String openToken, String closeToken, TokenHandler tokenHandler) {
        this.openToken = openToken;
        this.closeToken = closeToken;
        this.tokenHandler = tokenHandler;
    }

    /**
     * 为什么是逐渐追加模型。因为我们的SQL一般都是正确的。
     */
    public String parse(@NonNull String script) {
        if (script.indexOf("\\") > -1) {
            throw new IllegalArgumentException("脚本中含有\\");
        }
        int openTokenIndex0 = script.indexOf(openToken);
        if (openTokenIndex0 == -1) {
            return script;
        }
        int closeTokenIndex0 = script.indexOf(closeToken);
        if (closeTokenIndex0 == -1) {
            return script;
        }
        //
        int openTokenIndex = openTokenIndex0;
        char[] chars = script.toCharArray();
        int index = 0;
        final StringBuilder sb = new StringBuilder();
        StringBuilder expression = null;
        do {
            //found open token.
            if (expression == null) {
                expression = new StringBuilder();
            } else {
                expression.setLength(0);
            }
            //保存的数据是openToken之前的值
            sb.append(chars, index, openTokenIndex - index);
            index = openTokenIndex + openToken.length();
            //search close token.
            int closeTokenIndex = script.indexOf(closeToken, index);
            if (closeTokenIndex > -1) {
                expression.append(chars, index, closeTokenIndex - index);
                sb.append(tokenHandler.handle(expression.toString()));
                //
                index = closeTokenIndex + closeToken.length();
                openTokenIndex = script.indexOf(openToken, index);
                if (openTokenIndex == -1) {
                    if (index < chars.length) {
                        sb.append(chars, index, chars.length - index);
                    }
                }
            } else {
                // close token was not found.
                sb.append(chars, openTokenIndex, chars.length - openTokenIndex);
                break;
            }
        } while (openTokenIndex > -1);
        return sb.toString();
    }
}
